/* This file is part of MyRename
 * Copyright (C) 2005-2009 Kai-Chieh Ku (kjackie@gmail.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

// PreListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "MyRename.h"
#include "MyRenamedlg.h"
#include "preferences.h"
#include "language.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// CPreListCtrl

IMPLEMENT_DYNAMIC(CPreListCtrl, CFileListCtrl)
CPreListCtrl::CPreListCtrl()
	: m_iEditItem(-1)
{
}

CPreListCtrl::~CPreListCtrl()
{
}

BEGIN_MESSAGE_MAP(CPreListCtrl, CFileListCtrl)
	//{{AFX_MSG_MAP(CPreListCtrl)
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnLvnColumnClick)
	ON_NOTIFY_REFLECT(LVN_ITEMACTIVATE, OnLvnItemActivate)
	ON_NOTIFY_REFLECT(LVN_ITEMCHANGED, OnLvnItemChanged)
	ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnLvnEndLabelEdit)
	ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnLvnBeginLabelEdit)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CPreListCtrl::Init()
{
	CFileListCtrl::Init();
	ModifyStyle(0, LVS_EDITLABELS);

	m_context.InsertMenu(ID_EDIT_SELECT_ALL, MF_BYCOMMAND, ID_EDIT_CLEAR, GetResString(IDS_EDIT_DELETE));
	m_context.InsertMenu(ID_EDIT_SELECT_ALL, MF_BYCOMMAND, ID_EDIT_REPLACE, GetResString(IDS_EDIT_RENAME));
	m_context.InsertMenu(ID_EDIT_SELECT_ALL, MF_SEPARATOR);

	SetColumns(&thePrefs.uaExtColOrder, &thePrefs.uaExtColWidth);
	SortList(thePrefs.uExtSortCol, thePrefs.bExtSortAsc != FALSE);
}

void CPreListCtrl::Localize()
{
	CFileListCtrl::Localize();
	m_context.ModifyMenu(ID_EDIT_CLEAR, MF_BYCOMMAND, ID_EDIT_CLEAR, GetResString(IDS_EDIT_DELETE));
	m_context.ModifyMenu(ID_EDIT_REPLACE, MF_BYCOMMAND, ID_EDIT_REPLACE, GetResString(IDS_EDIT_RENAME));
}

void CPreListCtrl::DeleteFiles()
{
	POSITION pos = GetFirstSelectedItemPosition();
	if (!pos)
		return;

	const bool bRecycled = ((GetKeyState(VK_SHIFT) & 0x8000) == 0);
	FILEWND->LockUpdate();
	TCHAR filepath[65535];
	LPTSTR pFilepath = filepath;
	bool del_ok;
	SHFILEOPSTRUCT fp = {0};

	fp.wFunc = FO_DELETE;
	fp.hwnd = MAINWND->m_hWnd;
	fp.fFlags = (bRecycled ? FOF_ALLOWUNDO : 0);
	fp.pFrom = filepath;

	while (pos)
		pFilepath += (_stprintf(pFilepath, _T("%s%s"), thePrefs.sLastPath, GetItemText(GetNextSelectedItem(pos), 0)) + 1);

	*pFilepath = _T('\0');

	del_ok = (SHFileOperation(&fp) == 0);

	FILEWND->UnlockUpdate();
	FILEWND->UpdateList(true, &thePrefs.fnMask);
}

void CPreListCtrl::EditFile()
{

	POSITION pos = GetFirstSelectedItemPosition();
	if (pos)
		EditLabel(GetNextSelectedItem(pos));
}

void CPreListCtrl::UpdateMenu()
{
	CFileListCtrl::UpdateMenu();

	const bool bSel = (GetFirstSelectedItemPosition() != NULL);
	m_context.EnableMenuItem(ID_EDIT_CLEAR, MF_BYCOMMAND | (bSel ? MF_ENABLED : MF_GRAYED));
	m_context.EnableMenuItem(ID_EDIT_REPLACE, MF_BYCOMMAND | (bSel ? MF_ENABLED : MF_GRAYED));
}

// CPreListCtrl message handlers

void CPreListCtrl::OnLvnColumnClick(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	SortList(pNMLV->iSubItem);
	thePrefs.uExtSortCol = m_sCol;
	thePrefs.bExtSortAsc = m_sAsc;
	FILEWND->UpdateList();
	FILEWND->KillTimer(FT_UPDATER); //avoid unnecessary update
	*pResult = 0;
}

void CPreListCtrl::OnLvnItemActivate(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMIA = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	if (pNMIA->iItem < GetItemCount() && pNMIA->iItem >= 0) {
		CFileName *pData = (CFileName *) GetItemData(pNMIA->iItem);
		if (pData->isFolder())
			FILEWND->m_DirTree.SelectChildItem(pData->GetName());
	}
	*pResult = 0;
}

void CPreListCtrl::OnLvnItemChanged(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	FILEWND->KillTimer(FT_UPDATER);
	FILEWND->SetTimer(FT_UPDATER, 500, NULL);
	*pResult = 0;
}

void CPreListCtrl::OnLvnBeginLabelEdit(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
	
	m_iEditItem = pDispInfo->item.iItem;
	m_sEditName = GetItemText(m_iEditItem, 0);

	theApp.m_bPostReturn = false;

	*pResult = 0;
}

void CPreListCtrl::OnLvnEndLabelEdit(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);

	if (pDispInfo->item.iItem == m_iEditItem && pDispInfo->item.pszText && m_sEditName != pDispInfo->item.pszText) {
		MoveFile(thePrefs.sLastPath + m_sEditName, thePrefs.sLastPath + pDispInfo->item.pszText);
		FILEWND->UpdateList(true, &thePrefs.fnMask);
	}

	m_iEditItem = -1;
	theApp.m_bPostReturn = true;

	*pResult = 0;
}

BOOL CPreListCtrl::OnCommand(WPARAM wParam, LPARAM lParam)
{
	switch (HIWORD(wParam)) {
		case 0: //from menu items
		case 1: //from accelerators
			switch (LOWORD(wParam)) {
				case ID_EDIT_CLEAR:
					DeleteFiles();
					return TRUE;
				case ID_EDIT_REPLACE:
					EditFile();
					return TRUE;
			}
			break;
	}

	return CFileListCtrl::OnCommand(wParam, lParam);
}

LRESULT CPreListCtrl::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message) {
		case WM_KEYDOWN:
		case WM_SYSKEYDOWN:
			{
				switch (wParam) {
					case VK_DELETE:
						SendMessage(WM_COMMAND, 0x00010000 | ID_EDIT_CLEAR);
						return TRUE;
					case VK_F2:
						SendMessage(WM_COMMAND, 0x00010000 | ID_EDIT_REPLACE);
						return TRUE;
				}
			}
			break;
	}

	return CFileListCtrl::DefWindowProc(message, wParam, lParam);
}
